<?php

namespace sws\route;

use sws\Container;

class RouteRule
{
    /**
     * 路由支持的方法
     * @var string[]
     */
    protected $methods = ['GET', 'POST', 'DELETE', 'HEAD', 'PATCH', 'PUT', 'OPTION'];

    /**
     * 当前路由设置的方法
     * @var array|string[]
     */
    public $method;

    /**
     * 当前路由名
     * @var string
     */
    private $route;

    /**
     * 路由目标方法
     * @var mixed
     */
    public $handler;

    /**
     * 路由分组对象
     * @var RouteGroup
     */
    private $routeGroup;

    /**
     * 当前路由中间件
     * @var array
     */
    private $middleware = [];

    /**
     * @param mixed  $method
     * @param string $route
     * @param mixed  $handler
     * @param        $routeGroup
     */
    public function __construct($method, string $route, $handler, $routeGroup)
    {
        if (is_string($method)) {
            if ($method == '*') {
                $method = $this->methods;
            } else {
                $method = [strtoupper($method)];
            }
        } else {
            $method = (array)$method;
            foreach ($method as &$value) {
                $value = strtoupper($value);
            }
        }

        $this->method = $method;
        if(is_string($handler) && strstr($handler,'@')){
            $handler = explode('@',$handler);
        }
        $this->handler = $handler;
        $this->routeGroup = $routeGroup;
        $this->route = $route;
    }

    /**
     * 当前路由添加中间件
     * @param $middleware
     * @param ...$params
     * @return $this
     */
    public function middleware($middleware, ...$params): RouteRule
    {
        if (is_array($middleware)) {
            $this->middleware = array_merge($this->middleware, $middleware);
        } else {
            array_unshift($params, $middleware);
            $this->middleware = array_merge($this->middleware, $params);
        }
        return $this;
    }

    /**
     * 获取解析参数
     * @return array
     */
    public function getParseData(): array
    {
        return Container::getInstance()->make(RouteParser::class)->parse($this->getRoute());
    }

    /**
     * 获取路由名
     * @return string
     */
    private function getRoute(): string
    {
        return $this->routeGroup->getGroupName() . $this->route;
    }

    /**
     * 获取路由解析树
     * @return array
     */
    public function getRouteTree(): array
    {
        $parseData = Container::getInstance()->make(RouteParser::class)->parse($this->getRoute());
        $routeTree = [];
        foreach ($parseData as $parseDatum) {
            //静态路由
            if (count($parseDatum) === 1 && is_string($parseDatum[0])) {
                foreach ($this->getMethod() as $method) {
                    $routeTree['static'][$method][$parseDatum[0]] = [
                        'handle' => $this->getHandler(),
                        'middleware' => $this->getMiddleware(),
                        'variable' => []
                    ];
                }
            } else { //动态路由
                $regex = '';
                $variable = [];
                foreach ($parseDatum as $part) {
                    if (is_string($part)) {
                        $regex .= preg_quote($part, '~');
                        continue;
                    }
                    [$varName, $regexPart] = $part;
                    $variable[] = $varName;
                    $regex .= '(' . $regexPart . ')';
                }
                foreach ($this->getMethod() as $method) {
                    $routeTree['dynamic'][$method][$regex] = [
                        'handle' => $this->getHandler(),
                        'middleware' => $this->getMiddleware(),
                        'variable' => $variable
                    ];
                }
            }
        }
        return $routeTree;
    }

    /**
     * 获取方法
     * @return array|string[]
     */
    public function getMethod(): array
    {
        return $this->method;
    }

    /**
     * 获取路由指向的方法
     * @return mixed
     */
    public function getHandler()
    {
        return $this->handler;
    }

    /**
     * 当前路由中间件
     * @return array
     */
    public function getMiddleware(): array
    {
        return array_merge($this->routeGroup->getMiddleware(), $this->middleware);
    }

}